home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
Source
/
POVSRC
/
SOURCE
/
CSG.C
< prev
next >
Wrap
Text File
|
1993-10-28
|
10KB
|
392 lines
/****************************************************************************
* csg.c
*
* This module implements routines for constructive solid geometry.
*
* from Persistence of Vision Raytracer
* Copyright 1993 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file. If
* POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by leaving a message in CompuServe's Graphics Developer's
* Forum. The latest version of POV-Ray may be found there as well.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*****************************************************************************/
#include "frame.h"
#include "vector.h"
#include "povproto.h"
METHODS CSG_Union_Methods =
{
All_CSG_Union_Intersections,
Inside_CSG_Union, NULL /*Normal*/,
Copy_CSG,
Translate_CSG, Rotate_CSG,
Scale_CSG, Transform_CSG, Invert_CSG_Union, Destroy_CSG
};
METHODS CSG_Merge_Methods =
{
All_CSG_Merge_Intersections,
Inside_CSG_Union, NULL /*Normal*/,
Copy_CSG,
Translate_CSG, Rotate_CSG,
Scale_CSG, Transform_CSG, Invert_CSG_Union, Destroy_CSG
};
METHODS CSG_Intersection_Methods =
{
All_CSG_Intersect_Intersections,
Inside_CSG_Intersection, NULL /*Normal*/,
Copy_CSG,
Translate_CSG, Rotate_CSG,
Scale_CSG, Transform_CSG, Invert_CSG_Intersection, Destroy_CSG
};
int All_CSG_Union_Intersections (Object, Ray, Depth_Stack)
OBJECT *Object;
RAY *Ray;
ISTACK *Depth_Stack;
{
register int Found;
OBJECT *Current_Sib, *Clip;
ISTACK *Local_Stack;
INTERSECTION *Sibling_Intersection;
Found = FALSE;
if ((Clip = Object->Clip) == NULL) /* Use shortcut if no clip */
{
for (Current_Sib = ((CSG *)Object)->Children;
Current_Sib != NULL ;
Current_Sib = Current_Sib->Sibling)
if (Ray_In_Bounds (Ray, Current_Sib->Bound))
if (All_Intersections (Current_Sib, Ray, Depth_Stack))
Found = TRUE;
}
else
{
Local_Stack = open_istack ();
for (Current_Sib = ((CSG *)Object)->Children;
Current_Sib != NULL ;
Current_Sib = Current_Sib->Sibling)
if (Ray_In_Bounds (Ray, Current_Sib->Bound))
if (All_Intersections (Current_Sib, Ray, Local_Stack))
while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
if (Point_In_Clip (&Sibling_Intersection->IPoint, Clip))
{
push_copy (Depth_Stack, Sibling_Intersection);
Found = TRUE;
}
close_istack (Local_Stack);
}
return (Found);
}
int All_CSG_Intersect_Intersections (Object, Ray, Depth_Stack)
OBJECT *Object;
RAY *Ray;
ISTACK *Depth_Stack;
{
int Maybe_Found, Found;
OBJECT *Current_Sib, *Inside_Sib;
ISTACK *Local_Stack;
INTERSECTION *Sibling_Intersection;
Local_Stack = open_istack ();
Found = FALSE;
for (Current_Sib = ((CSG *)Object)->Children;
Current_Sib != NULL;
Current_Sib = Current_Sib->Sibling)
{
if (Ray_In_Bounds (Ray, Current_Sib->Bound))
if (All_Intersections (Current_Sib, Ray, Local_Stack))
while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
{
Maybe_Found = TRUE;
for (Inside_Sib = ((CSG *)Object)->Children;
Inside_Sib != NULL;
Inside_Sib = Inside_Sib->Sibling)
if (Inside_Sib != Current_Sib)
if (!Inside_Object (&Sibling_Intersection->IPoint, Inside_Sib))
{
Maybe_Found = FALSE;
break;
}
if (Maybe_Found)
if (Point_In_Clip (&Sibling_Intersection->IPoint, Object->Clip))
{
push_copy(Depth_Stack, Sibling_Intersection);
Found = TRUE;
}
}
}
close_istack (Local_Stack);
return (Found);
}
int All_CSG_Merge_Intersections (Object, Ray, Depth_Stack)
OBJECT *Object;
RAY *Ray;
ISTACK *Depth_Stack;
{
register int Found, inside_flag;
OBJECT *Sib1, *Sib2;
ISTACK *Local_Stack;
INTERSECTION *Sibling_Intersection;
Found = FALSE;
Local_Stack = open_istack ();
for (Sib1 = ((CSG *)Object)->Children;
Sib1 != NULL ;
Sib1 = Sib1->Sibling)
if (Ray_In_Bounds (Ray, Sib1->Bound))
if (All_Intersections (Sib1, Ray, Local_Stack))
while ((Sibling_Intersection = pop_entry (Local_Stack)) != NULL)
if (Point_In_Clip (&Sibling_Intersection->IPoint,Object->Clip))
{
inside_flag = TRUE;
for (Sib2 = ((CSG *)Object)->Children;
Sib2 != NULL && inside_flag == TRUE;
Sib2 = Sib2->Sibling)
if (Sib1 != Sib2)
if (Inside_Object(&Sibling_Intersection->IPoint,Sib2))
inside_flag = FALSE;
if (inside_flag == TRUE)
{
Found = TRUE;
push_copy (Depth_Stack, Sibling_Intersection);
}
}
close_istack (Local_Stack);
return (Found);
}
int Inside_CSG_Union (IPoint, Object)
VECTOR *IPoint;
OBJECT *Object;
{
OBJECT *Current_Sib;
for (Current_Sib = ((CSG *)Object)->Children;
Current_Sib != NULL ;
Current_Sib = Current_Sib->Sibling)
if (Inside_Object (IPoint, Current_Sib))
return (TRUE);
return (FALSE);
}
int Inside_CSG_Intersection (IPoint, Object)
OBJECT *Object;
VECTOR *IPoint;
{
OBJECT *Current_Sib;
for (Current_Sib = ((CSG *)Object)->Children;
Current_Sib != NULL ;
Current_Sib = Current_Sib->Sibling)
if (!Inside_Object (IPoint, Current_Sib))
return (FALSE);
return (TRUE);
}
void *Copy_CSG (Object)
OBJECT *Object;
{
CSG *New;
OBJECT *Old_Sib, *New_Sib, *Prev_Sib;
if ((New = (CSG *) malloc (sizeof (CSG))) == NULL)
MAError ("CSG");
New->Children = Prev_Sib = NULL;
for (Old_Sib = ((CSG *)Object)->Children;
Old_Sib != NULL ;
Old_Sib = Old_Sib->Sibling)
{
New_Sib = Copy_Object (Old_Sib);
if (New->Children == NULL)
New->Children = New_Sib;
if (Prev_Sib != NULL)
Prev_Sib->Sibling = New_Sib;
Prev_Sib = New_Sib;
}
return (New);
}
void Translate_CSG (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
OBJECT *Sib;
for (Sib = ((CSG *) Object)->Children;
Sib != NULL ;
Sib = Sib->Sibling)
Translate_Object (Sib, Vector);
Compute_CSG_Bounds(Object);
}
void Rotate_CSG (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
OBJECT *Sib;
for (Sib = ((CSG *) Object)->Children;
Sib != NULL ;
Sib = Sib->Sibling)
Rotate_Object (Sib, Vector);
Compute_CSG_Bounds(Object);
}
void Scale_CSG (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
OBJECT *Sib;
for (Sib = ((CSG *) Object)->Children;
Sib != NULL ;
Sib = Sib->Sibling)
Scale_Object (Sib, Vector);
Compute_CSG_Bounds(Object);
}
void Transform_CSG (Object, Trans)
OBJECT *Object;
TRANSFORM *Trans;
{
OBJECT *Sib;
for (Sib = ((CSG *) Object)->Children;
Sib != NULL ;
Sib = Sib->Sibling)
Transform_Object (Sib, Trans);
Compute_CSG_Bounds(Object);
}
void Destroy_CSG (Object)
OBJECT *Object;
{
Destroy_Object (((CSG *) Object)->Children);
free (Object);
}
void Invert_CSG_Union (Object)
OBJECT *Object;
{
OBJECT *Sib;
Object->Methods = &CSG_Intersection_Methods;
for (Sib = ((CSG *)Object)->Children;
Sib != NULL ;
Sib = Sib->Sibling)
Invert_Object (Sib);
}
void Invert_CSG_Intersection (Object)
OBJECT *Object;
{
OBJECT *Sib;
Object->Methods = &CSG_Union_Methods;
for (Sib = ((CSG *)Object)->Children;
Sib != NULL ;
Sib = Sib->Sibling)
Invert_Object (Sib);
}
CSG *Create_CSG_Union ()
{
CSG *New;
if ((New = (CSG *) malloc (sizeof (CSG))) == NULL)
MAError ("union");
INIT_OBJECT_FIELDS(New, UNION_OBJECT, &CSG_Union_Methods)
New->Children = NULL;
return (New);
}
CSG *Create_CSG_Merge ()
{
CSG *New;
if ((New = (CSG *) malloc (sizeof (CSG))) == NULL)
MAError ("merge");
INIT_OBJECT_FIELDS(New, MERGE_OBJECT, &CSG_Merge_Methods)
New->Children = NULL;
return (New);
}
CSG *Create_CSG_Intersection ()
{
CSG *New;
if ((New = (CSG *) malloc (sizeof (CSG))) == NULL)
MAError ("intersection");
INIT_OBJECT_FIELDS(New, INTERSECTION_OBJECT, &CSG_Intersection_Methods)
New->Children = NULL;
return (New);
}
void Compute_CSG_Bounds (Object)
OBJECT *Object;
{
VECTOR mins, maxs;
DBL tmin, tmax;
OBJECT *Sib;
Make_Vector(&mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
Make_Vector(&maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
for (Sib = ((CSG *) Object)->Children;
Sib != NULL ;
Sib = Sib->Sibling)
{
tmin = Sib->Bounds.Lower_Left.x;
tmax = Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x;
if (tmin < mins.x) mins.x = tmin;
if (tmax > maxs.x) maxs.x = tmax;
tmin = Sib->Bounds.Lower_Left.y;
tmax = Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y;
if (tmin < mins.y) mins.y = tmin;
if (tmax > maxs.y) maxs.y = tmax;
tmin = Sib->Bounds.Lower_Left.z;
tmax = Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z;
if (tmin < mins.z) mins.z = tmin;
if (tmax > maxs.z) maxs.z = tmax;
}
Object->Bounds.Lower_Left = mins;
VSub(Object->Bounds.Lengths, maxs, mins);
}